home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / nasm095s.zip / RDOFF / RDOFF.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  9KB  |  398 lines

  1. /* rdoff.c       library of routines for manipulating rdoff files
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  */
  8.  
  9. /* TODO:    The functions in this module assume they are running
  10.  *        on a little-endian machine. This should be fixed to
  11.  *        make it portable.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <errno.h>
  18.  
  19. #include "rdoff.h"
  20.  
  21. #define newstr(str) strcpy(malloc(strlen(str) + 1),str)
  22. #define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1) + strlen(s2) + 1), \
  23.                                        s1),s2)
  24.  
  25. /* ========================================================================
  26.  * Code for memory buffers (for delayed writing of header until we know
  27.  * how long it is).
  28.  * ======================================================================== */
  29.  
  30.  
  31. memorybuffer * newmembuf(){
  32.   memorybuffer * t;
  33.  
  34.   t = malloc(sizeof(memorybuffer));
  35.  
  36.   t->length = 0;
  37.   t->next = NULL;
  38.   return t;
  39. }
  40.  
  41. void membufwrite(memorybuffer *b, void *data, int bytes) {
  42.   int16 w;
  43.   long l;
  44.  
  45.   if (b->next) {        /* memory buffer full - use next buffer */
  46.     membufwrite(b->next,data,bytes);
  47.     return;
  48.   }
  49.   if ((bytes < 0 && b->length - bytes > BUF_BLOCK_LEN)
  50.       || (bytes > 0 && b->length + bytes > BUF_BLOCK_LEN)) {
  51.     
  52.     /* buffer full and no next allocated... allocate and initialise next
  53.      * buffer */
  54.  
  55.     b->next = newmembuf();
  56.     membufwrite(b->next,data,bytes);
  57.   }
  58.  
  59.   switch(bytes) {
  60.   case -4:              /* convert to little-endian */
  61.     l = * (long *) data ;
  62.     b->buffer[b->length++] = l & 0xFF;
  63.     l >>= 8 ;
  64.     b->buffer[b->length++] = l & 0xFF;
  65.     l >>= 8 ;
  66.     b->buffer[b->length++] = l & 0xFF;
  67.     l >>= 8 ;
  68.     b->buffer[b->length++] = l & 0xFF;
  69.     break;
  70.  
  71.   case -2:
  72.     w = * (int16 *) data ;
  73.     b->buffer[b->length++] = w & 0xFF;
  74.     w >>= 8 ;
  75.     b->buffer[b->length++] = w & 0xFF;
  76.     break;
  77.  
  78.   default:
  79.     while(bytes--) {
  80.       b->buffer[b->length++] = *(* (unsigned char **) &data);
  81.  
  82.       (* (unsigned char **) &data)++ ;
  83.     }
  84.     break;
  85.   }
  86. }
  87.  
  88. void membufdump(memorybuffer *b,FILE *fp)
  89. {
  90.   if (!b) return;
  91.  
  92.   fwrite (b->buffer, 1, b->length, fp);
  93.   
  94.   membufdump(b->next,fp);
  95. }
  96.  
  97. int membuflength(memorybuffer *b)
  98. {
  99.   if (!b) return 0;
  100.   return b->length + membuflength(b->next);
  101. }
  102.  
  103. void freemembuf(memorybuffer *b)
  104. {
  105.   if (!b) return;
  106.   freemembuf(b->next);
  107.   free(b);
  108. }
  109.  
  110. /* =========================================================================
  111.    General purpose routines and variables used by the library functions
  112.    ========================================================================= */
  113.  
  114. long translatelong(long in) {           /* translate from little endian to
  115.                                            local representation */
  116.   long r;
  117.   unsigned char *i;
  118.  
  119.   i = (unsigned char *)∈
  120.   r = i[3];
  121.   r = (r << 8) + i[2];
  122.   r = (r << 8) + i[1];
  123.   r = (r << 8) + *i;
  124.  
  125.   return r;
  126. }
  127.  
  128. const char *RDOFFId = "RDOFF1"; /* written to the start of RDOFF files */
  129.  
  130. const char *rdf_errors[7] = {
  131.   "no error occurred","could not open file","invalid file format",
  132.   "error reading file","unknown error","header not read",
  133.   "out of memory"};
  134.  
  135. int rdf_errno = 0;
  136.  
  137. /* ========================================================================
  138.    The library functions
  139.    ======================================================================== */
  140.  
  141. int rdfopen(rdffile *f, const char *name)
  142. {
  143.     FILE * fp;
  144.  
  145.     fp = fopen(name,"rb");
  146.     if (!fp) return rdf_errno = 1;        /* error 1: file open error */
  147.  
  148.     return rdfopenhere(f,fp,NULL,"");
  149. }
  150.  
  151. int rdfopenhere(rdffile *f, FILE *fp, int *refcount, char *name)
  152. {
  153.   char buf[8];
  154.   long initpos;
  155.  
  156.   if (translatelong(0x01020304) != 0x01020304)
  157.   {                    /* fix this to be portable! */
  158.     fputs("*** this program requires a little endian machine\n",stderr);
  159.     fprintf(stderr,"01020304h = %08lxh\n",translatelong(0x01020304));
  160.     exit(3);
  161.   }
  162.  
  163.   f->fp = fp;
  164.   initpos = ftell(fp);
  165.  
  166.   fread(buf,6,1,f->fp);        /* read header */
  167.   buf[6] = 0;
  168.  
  169.   if (strcmp(buf,RDOFFId)) {
  170.     fclose(f->fp);
  171.     return rdf_errno = 2;     /* error 2: invalid file format */
  172.   }
  173.  
  174.   if (fread(&f->header_len,1,4,f->fp) != 4) {
  175.     fclose(f->fp);
  176.     return rdf_errno = 3;    /* error 3: file read error */
  177.   }
  178.  
  179.   f->header_ofs = ftell(f->fp);
  180.  
  181.   if (fseek(f->fp,f->header_len,SEEK_CUR)) {
  182.     fclose(f->fp);
  183.     return rdf_errno = 2;    /* seek past end of file...? */
  184.   }
  185.  
  186.   if (fread(&f->code_len,1,4,f->fp) != 4) {
  187.     fclose(f->fp);
  188.     return rdf_errno = 3;
  189.   }
  190.  
  191.   f->code_ofs = ftell(f->fp);
  192.   if (fseek(f->fp,f->code_len,SEEK_CUR)) {
  193.     fclose(f->fp);
  194.     return rdf_errno = 2;
  195.   }
  196.  
  197.   if (fread(&f->data_len,1,4,f->fp) != 4) {
  198.     fclose(f->fp);
  199.     return rdf_errno = 3;
  200.   }
  201.  
  202.   f->data_ofs = ftell(f->fp);
  203.   fseek(f->fp,initpos,SEEK_SET);
  204.   f->header_loc = NULL;
  205.  
  206.   f->name = newstr(name);
  207.   f->refcount = refcount;
  208.   if (refcount) (*refcount)++;
  209.   return 0;
  210. }
  211.  
  212. int rdfclose(rdffile *f)
  213. {
  214.     if (! f->refcount || ! *--f->refcount)
  215.     fclose(f->fp);
  216.     free(f->name);
  217.  
  218.     return 0;
  219. }
  220.  
  221. void rdfperror(const char *app,const char *name)
  222. {
  223.   fprintf(stderr,"%s:%s: %s\n",app,name,rdf_errors[rdf_errno]);
  224.   if (rdf_errno == 1 || rdf_errno == 3)
  225.   {
  226.       perror(app);
  227.   }
  228.  
  229. }
  230.  
  231. int rdfloadseg(rdffile *f,int segment,void *buffer)
  232. {
  233.   long fpos;
  234.   long slen;
  235.  
  236.   switch(segment) {
  237.   case RDOFF_HEADER:
  238.     fpos = f->header_ofs;
  239.     slen = f->header_len;
  240.     f->header_loc = (char *)buffer;
  241.     f->header_fp = 0;
  242.     break;
  243.   case RDOFF_CODE:
  244.     fpos = f->code_ofs;
  245.     slen = f->code_len;
  246.     break;
  247.   case RDOFF_DATA:
  248.     fpos = f->data_ofs;
  249.     slen = f->data_len;
  250.     break;
  251.   default:
  252.     fpos = 0;
  253.     slen = 0;
  254.   }
  255.  
  256.   if (fseek(f->fp,fpos,SEEK_SET))
  257.     return rdf_errno = 4;    
  258.     
  259.   if (fread(buffer,1,slen,f->fp) != slen)
  260.     return rdf_errno = 3;
  261.  
  262.   return 0;
  263. }
  264.  
  265. /* Macros for reading integers from header in memory */
  266.  
  267. #define RI8(v) v = f->header_loc[f->header_fp++]
  268. #define RI16(v) { v = (f->header_loc[f->header_fp] + \
  269.                (f->header_loc[f->header_fp+1] << 8)); \
  270.           f->header_fp += 2; }
  271.  
  272. #define RI32(v) { v = (f->header_loc[f->header_fp] + \
  273.                (f->header_loc[f->header_fp+1] << 8) + \
  274.                (f->header_loc[f->header_fp+2] << 16) + \
  275.                (f->header_loc[f->header_fp+3] << 24)); \
  276.           f->header_fp += 4; }
  277.  
  278. #define RS(str,max) { for(i=0;i<max;i++){\
  279.   RI8(str[i]); if (!str[i]) break;} str[i]=0; }
  280.  
  281. rdfheaderrec *rdfgetheaderrec(rdffile *f)
  282. {
  283.   static rdfheaderrec r;
  284.   int i;
  285.  
  286.   if (!f->header_loc) {
  287.     rdf_errno = 5;
  288.     return NULL;
  289.   }
  290.  
  291.   if (f->header_fp >= f->header_len) return 0;
  292.  
  293.   RI8(r.type);
  294.   switch(r.type) {
  295.   case 1:    /* Relocation record */
  296.     RI8(r.r.segment);
  297.     RI32(r.r.offset);
  298.     RI8(r.r.length);
  299.     RI16(r.r.refseg);
  300.     break;
  301.  
  302.   case 2:    /* Imported symbol record */
  303.     RI16(r.i.segment);
  304.     RS(r.i.label,32);
  305.     break;
  306.  
  307.   case 3:    /* Exported symbol record */
  308.     RI8(r.e.segment);
  309.     RI32(r.e.offset);
  310.     RS(r.e.label,32);
  311.     break;
  312.  
  313.   case 4:    /* DLL record */
  314.     RS(r.d.libname,127);
  315.     break;
  316.  
  317.   case 5:    /* BSS reservation record */
  318.     RI32(r.b.amount);
  319.     break;
  320.  
  321.   default:
  322.     rdf_errno = 2; /* invalid file */
  323.     return NULL;
  324.   }
  325.   return &r;
  326. }
  327.     
  328. void rdfheaderrewind(rdffile *f)
  329. {
  330.   f->header_fp = 0;
  331. }
  332.  
  333.  
  334. rdf_headerbuf * rdfnewheader(void)
  335. {
  336.     return newmembuf();
  337. }
  338.  
  339. int rdfaddheader(rdf_headerbuf * h, rdfheaderrec * r)
  340. {
  341.     switch (r->type)
  342.     {
  343.     case 1:
  344.     membufwrite(h,&r->type,1);
  345.     membufwrite(h,&r->r.segment,1);
  346.     membufwrite(h,&r->r.offset,-4);
  347.     membufwrite(h,&r->r.length,1);
  348.     membufwrite(h,&r->r.refseg,-2);    /* 9 bytes written */
  349.     break;
  350.  
  351.     case 2:                /* import */
  352.     membufwrite(h,&r->type,1);
  353.     membufwrite(h,&r->i.segment,-2);
  354.     membufwrite(h,&r->i.label,strlen(r->i.label) + 1);
  355.     break ;
  356.  
  357.     case 3:                /* export */
  358.     membufwrite(h,&r->type,1);
  359.     membufwrite(h,&r->e.segment,1);
  360.     membufwrite(h,&r->e.offset,-4);
  361.     membufwrite(h,&r->e.label,strlen(r->e.label) + 1);
  362.     break ;
  363.  
  364.     case 4:                /* DLL */
  365.     membufwrite(h,&r->type,1);
  366.     membufwrite(h,&r->d.libname,strlen(r->d.libname) + 1);
  367.     break ;
  368.  
  369.     case 5:                /* BSS */
  370.     membufwrite(h,&r->type,1);
  371.     membufwrite(h,&r->b.amount,-4);
  372.     break ;
  373.  
  374.     default:
  375.     return (rdf_errno = 2);
  376.     }
  377.     return 0;
  378. }
  379.  
  380. int rdfwriteheader(FILE * fp, rdf_headerbuf * h)
  381. {
  382.     long        l;
  383.  
  384.     fwrite (RDOFFId, 1, strlen(RDOFFId), fp) ;
  385.  
  386.     l = translatelong ( membuflength (h) );
  387.     fwrite (&l, 4, 1, fp);
  388.  
  389.     membufdump(h, fp);
  390.  
  391.     return 0;        /* no error handling in here... CHANGE THIS! */
  392. }
  393.  
  394. void rdfdoneheader(rdf_headerbuf * h)
  395. {
  396.     freemembuf(h);
  397. }
  398.